#include "adc.h"

// 查看原理图得，ADKey 连接 PC1，当某个按键按下时，由 R21 电阻和相应按键的串联电阻组成串联电路，
// 输入对应的电压值到 PC1，由 ADC 转换为数字值，从而得知哪个按键按下。
// 选择 ADC1 通道 11 对 PC1 进行转换

/**
 * 简述：初始化 ADC1 通道11
 * 参数：无
 * 返回值：无
 **/
void adc1_ch11_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	ADC_InitTypeDef ADC_InitStruct;
	
	// 使能 GPIOC 和 ADC1 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1, ENABLE);
	
	// 配置 ADC1 时钟
	// void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);
	RCC_ADCCLKConfig(RCC_PCLK2_Div2);
	
	// 配置 PC1 为模拟输入
	GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_1;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	// 初始化 ADC1
	ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;  // 不连续转换
	ADC_InitStruct.ADC_DataAlign          = ADC_DataAlign_Right;  // 右对齐
	ADC_InitStruct.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;  // 不使用外部触发
	ADC_InitStruct.ADC_Mode               = ADC_Mode_Independent;  // 独立模式
	ADC_InitStruct.ADC_NbrOfChannel       = 1;  // 通道数
	ADC_InitStruct.ADC_ScanConvMode       = DISABLE;  // 禁用描述模式
	// void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
	ADC_Init(ADC1, &ADC_InitStruct);
	
	// 使能 ADC1
	// void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
	ADC_Cmd(ADC1, ENABLE);
	
	// 对 ADC1 进行校准
	// 复位校准
	// void ADC_ResetCalibration(ADC_TypeDef* ADCx);
	ADC_ResetCalibration(ADC1);
	// FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	
	// 校准
	// void ADC_StartCalibration(ADC_TypeDef* ADCx);
	ADC_StartCalibration(ADC1);
	// FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
}

/**
 * 简述：启动并获取 ADC1 通道11 的转换结果
 * 参数：无
 * 返回值：转换结果
 **/
uint16_t adc1_ch11_get_adkey_value(void)
{
	// 配置规则通道
	// void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
	
	// 软件启动转换
	// void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
	// 等待转换完成
	// FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

	// 获取转换值
	// uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
	return ADC_GetConversionValue(ADC1);
}
